﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Continuum.Classes;

namespace Continuum
{
    public partial class EditFunds : Form
    {
        private enum CurrentFormStateEnum { View, Add, Edit };
        private CurrentFormStateEnum CurrentFormState;
        Fund CurrentFund = null;

        public EditFunds()
        {
            InitializeComponent();
            SetupTooltips();
        }

        private void SetFormState(CurrentFormStateEnum NewFormState)
        {
            CurrentFormState = NewFormState;

            if (NewFormState == CurrentFormStateEnum.Add)
            {
                txtFundName.Enabled = true;
                dtpInceptionDate.Enabled = true;
                txtInceptionAmount.Enabled = true;
                txtEquityOffset.Enabled = true;
                rbDebt.Enabled = true;
                rbDebtEquity.Enabled = true;
                rbSavings.Enabled = true;
                rbSpending.Enabled = true;
                chkBenchmark.Enabled = true;
                chkHidden.Enabled = true;
            }

            if (NewFormState == CurrentFormStateEnum.Edit)
            {
                txtFundName.Enabled = true;
                dtpInceptionDate.Enabled = true;
                txtInceptionAmount.Enabled = true;
                txtEquityOffset.Enabled = true;
                rbDebt.Enabled = true;
                rbDebtEquity.Enabled = true;
                rbSavings.Enabled = true;
                rbSpending.Enabled = true;
                chkBenchmark.Enabled = true;
                chkHidden.Enabled = true;
            }

            if (NewFormState == CurrentFormStateEnum.View)
            {
                txtFundName.Enabled = false;
                dtpInceptionDate.Enabled = false;
                txtInceptionAmount.Enabled = false;
                txtEquityOffset.Enabled = false;
                rbDebt.Enabled = false;
                rbDebtEquity.Enabled = false;
                rbSavings.Enabled = false;
                rbSpending.Enabled = false;
                chkBenchmark.Enabled = false;
                chkHidden.Enabled = false;
            }

        }

        private void SetupTooltips()
        {
            System.Windows.Forms.ToolTip tip1 = new ToolTip();
            tip1.SetToolTip(rbDebt, "Debt Funds add no equity.\r\nThis might be used for auto loans, student loans, etc.");

            System.Windows.Forms.ToolTip tip2 = new ToolTip();
            tip2.SetToolTip(rbDebtEquity, "Debt Equity funds add value when paid down.\r\nThis might be used for home loans.");

            System.Windows.Forms.ToolTip tip3 = new ToolTip();
            tip3.SetToolTip(rbSavings, "Savings Funds add value.\r\nThis might be used for Savings accounts, IRA, 401K, etc.");

            System.Windows.Forms.ToolTip tip4 = new ToolTip();
            tip4.SetToolTip(rbSpending, "Spending Funds are typically used for primary checking accounts.\r\nThey do not add value and if not kept in balance, they indicate waste.");

            System.Windows.Forms.ToolTip tip5 = new ToolTip();
            tip4.SetToolTip(chkBenchmark, "Benchmark funds are artificial funds for comparison.\r\nThey do not add affect value or debt.");
        }

        private void EditFunds_Load(object sender, EventArgs e)
        {
            lstFunds.DataSource = null;
            lstFunds.DataSource = MainForm.projector.Funds;
        }

        private void ClearForm()
        {
            txtFundName.Text = "";
            dtpInceptionDate.Value = DateTime.Now.Date;
            txtInceptionAmount.Text = "0.00";
            txtEquityOffset.Text = "0.00";
            rbSavings.Checked = true;
            chkBenchmark.Checked = false;
            chkHidden.Checked = false;
            CurrentFund = null;
        }

        private void btnNewFund_Click(object sender, EventArgs e)
        {
            ClearForm();
            SetFormState(CurrentFormStateEnum.Add);
        }

        private bool ValidateFund()
        {
            string ValidationErrors = "";

            txtFundName.Text = txtFundName.Text.Trim();
            if (txtFundName.Text == "") ValidationErrors += "- You must enter a fund name\r\n";
            else
            {
                if (CurrentFund == null && MainForm.projector.FindFund(txtFundName.Text) != null) ValidationErrors += "A fund already exists with that name\r\n";
            }
            
            
            try { Decimal TempIncept = Decimal.Parse(txtInceptionAmount.Text); }
            catch {
                ValidationErrors += "- Inception Amount is not a valid Decimal\r\n";
            }

            try { Decimal TempEquityOffset = Decimal.Parse(txtEquityOffset.Text); }
            catch
            {
                ValidationErrors += "- Equity Offset is not a valid Decimal\r\n";
            }

            if (ValidationErrors.Length > 0)
            {
                MessageBox.Show("Please correct the following errors : \r\n" + ValidationErrors, "Unable to save fund due to validation errors", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return false;
            }

            return true;
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (!ValidateFund()) return;

            Decimal InceptionDecimal = Decimal.Parse(txtInceptionAmount.Text);
            Decimal EquityOffset = Decimal.Parse(txtEquityOffset.Text);

            FundClassEnum fundclass = FundClassEnum.Savings;
            if (rbDebt.Checked) fundclass = FundClassEnum.Debt;
            if (rbSpending.Checked) fundclass = FundClassEnum.SpendingAccount;
            if (rbDebtEquity.Checked) fundclass = FundClassEnum.DebtEquity;

            if (CurrentFormState == CurrentFormStateEnum.Add)
            {
                Balance newBal = new Balance(InceptionDecimal, dtpInceptionDate.Value.Date, "Inception Balance");

                CurrentFund = new Fund(newBal, txtFundName.Text, fundclass, chkBenchmark.Checked);
                CurrentFund.IsHidden = chkHidden.Checked;
                CurrentFund.EquityOffset = EquityOffset;
                MainForm.projector.Funds.Add(CurrentFund);
            }
            else // must be formstate.edit
            {
                // Maintain Integrity of Data Model --
                // If any funds are renamed then you will need to update actor fund references
                if (CurrentFund.Name != txtFundName.Text)
                {
                    foreach (Actor actor in MainForm.projector.Actors)
                    {
                        if (actor.ActorFundPrimary == CurrentFund.Name) actor.ActorFundPrimary = txtFundName.Text;
                        if (actor.ActorFundSecondary == CurrentFund.Name) actor.ActorFundSecondary = txtFundName.Text;
                    }
                }

                CurrentFund.Name = txtFundName.Text;
                CurrentFund.InceptionBalance.Amount = InceptionDecimal;
                CurrentFund.EquityOffset = EquityOffset;
                CurrentFund.InceptionBalance.BalanceDate = dtpInceptionDate.Value;
                CurrentFund.IsBenchmark = chkBenchmark.Checked;
                CurrentFund.IsHidden = chkHidden.Checked;

                CurrentFund.FundClass = fundclass;
            }

            // Flag Universe as Changed 
            MainForm.InstanceRef.HasChanged = true;

            lstFunds.DataSource = null;
            lstFunds.DataSource = MainForm.projector.Funds;
        }

        private void btnDeleteFund_Click(object sender, EventArgs e)
        {
            if (lstFunds.SelectedItem == null) return;

            Fund fund = (Fund)lstFunds.SelectedItem;

            string ActorNames="";
            foreach (Actor actor in MainForm.projector.Actors) 
            {
                if (actor.ActorFundPrimary == fund.Name || actor.ActorFundSecondary == fund.Name)
                    ActorNames += actor.ActorName + "\r\n";
            }
            if (ActorNames.Length > 0)
            {
                MessageBox.Show("You must fix the following Actors referencing this fund before the fund can be deleted : \r\n\r\n" + ActorNames, "Unable to delete Referenced Fund", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }

            if (MessageBox.Show("Are you sure you want to delete the fund '" + lstFunds.SelectedItem.ToString() + "'?", "Confirm fund deletion", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) != DialogResult.OK) return;

            // Flag Universe as Changed 
            MainForm.InstanceRef.HasChanged = true;

            MainForm.projector.Funds.Remove(fund);

            lstFunds.DataSource = null;
            lstFunds.DataSource = MainForm.projector.Funds;
        }

        private void lstFunds_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lstFunds.SelectedItem == null) return;

            Fund fund = (Fund) lstFunds.SelectedItem;
            CurrentFund = fund;

            txtFundName.Text = fund.Name;
            dtpInceptionDate.Value = fund.InceptionBalance.BalanceDate;
            txtInceptionAmount.Text = fund.InceptionBalance.Amount.ToString();
            txtEquityOffset.Text = fund.EquityOffset.ToString();
            chkBenchmark.Checked = fund.IsBenchmark;
            chkHidden.Checked = fund.IsHidden;

            switch (fund.FundClass)
            {
                case FundClassEnum.SpendingAccount: rbSpending.Checked = true; break;
                case FundClassEnum.Debt: rbDebt.Checked = true; break;
                case FundClassEnum.Savings: rbSavings.Checked = true; break;
                case FundClassEnum.DebtEquity: rbDebtEquity.Checked = true; break;
                default: rbSavings.Checked = true; break;
            }

            SetFormState(CurrentFormStateEnum.View);
        }

        private void btnEditHistorical_Click(object sender, EventArgs e)
        {
            if (lstFunds.SelectedItem == null) return;
            Fund fund = (Fund)lstFunds.SelectedItem;

            EditHistoricalBalances ehb = new EditHistoricalBalances();
            ehb.SetFund(fund);
            ehb.ShowDialog();
        }

        private void btnDone_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void btnEdit_Click(object sender, EventArgs e)
        {
            SetFormState(CurrentFormStateEnum.Edit);
        }

        private void lnkOnlineHelp_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.StartInfo.UseShellExecute = true;
            proc.StartInfo.FileName = "http://project-continuum.com/OnlineHelp/AdvancedFunds.aspx";
            proc.Start();
        }

        #region Simple Numeric Textbox Filtering

        private void txtInceptionAmount_KeyDown(object sender, KeyEventArgs e)
        {
            if (!(e.KeyValue >= '0' && e.KeyValue <= '9') && !(e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9)
                && e.KeyCode != Keys.Decimal && e.KeyCode != Keys.Back && e.KeyCode != Keys.OemPeriod
                && e.KeyCode != Keys.Delete && e.KeyCode != Keys.Insert && e.KeyCode != Keys.OemMinus && e.KeyCode != Keys.Subtract
                && e.KeyCode != Keys.Left && e.KeyCode != Keys.Right
               ) e.SuppressKeyPress = true;
        }

        private void txtEquityOffset_KeyDown(object sender, KeyEventArgs e)
        {
            if (!(e.KeyValue >= '0' && e.KeyValue <= '9') && !(e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9)
                && e.KeyCode != Keys.Decimal && e.KeyCode != Keys.Back && e.KeyCode != Keys.OemPeriod
                && e.KeyCode != Keys.Delete && e.KeyCode != Keys.Insert && e.KeyCode != Keys.OemMinus && e.KeyCode != Keys.Subtract
                && e.KeyCode != Keys.Left && e.KeyCode != Keys.Right
               ) e.SuppressKeyPress = true;
        }

        #endregion

    }
}
